package com.xiaobai.spike.service.oauth2.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xiaobai.spike.entity.OauthClientDetails;
import com.xiaobai.spike.entity.User;
import com.xiaobai.spike.model.request.AuthRequest;
import com.xiaobai.spike.model.request.TokenRequest;
import com.xiaobai.spike.model.response.TokenResponse;
import com.xiaobai.spike.sdk.lang.BusinessRuntimeException;
import com.xiaobai.spike.sdk.lang.Errors;
import com.xiaobai.spike.service.auth.UserService;
import com.xiaobai.spike.service.auth.impl.UserServiceImpl;
import com.xiaobai.spike.service.oauth2.AuthService;
import com.xiaobai.spike.service.client.OauthClientDetailsService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class AuthServiceImpl implements AuthService {

    private final static String CLIENT_AUTHORIZE_CODE = "client_authorize_Code_";

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private OauthClientDetailsService oauthClientDetailsService;

    @Resource
    private UserService userService;

    @Override
    public String authorizeCode(AuthRequest authRequest) {
        if (oauthClientDetailsService.getById(authRequest.getClient_id()) == null) {
            throw new BusinessRuntimeException(-1, "应用不存在，请前去注册");
        }

        User user = new User();
        user.setName(authRequest.getUsername());
        user.setPasswd(authRequest.getPassword());
        if(!userService.checkUserLogin(user)) {
            throw new BusinessRuntimeException(-1, "账号密码错误");
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("client_id",authRequest.getClient_id());
        jsonObject.put("username",user.getName());
        String code = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(CLIENT_AUTHORIZE_CODE + code, JSON.toJSONString(jsonObject), 72, TimeUnit.SECONDS);
        return code;
    }

    @Override
    public TokenResponse authorizeToken(TokenRequest tokenRequest) {
        OauthClientDetails oauthClientDetails = oauthClientDetailsService.getById(tokenRequest.getClient_id());
        if (oauthClientDetails == null) {
            throw new BusinessRuntimeException(-1, "应用不存在，请前去注册");
        }
        if (!Objects.equals(oauthClientDetails.getSecret(), tokenRequest.getClient_secret())) {
            throw new BusinessRuntimeException(-1, "client_secret校验失败");
        }
        Object o = redisTemplate.opsForValue().get(CLIENT_AUTHORIZE_CODE + tokenRequest.getCode());
        if (o == null) {
            throw new BusinessRuntimeException(-1, "code已失效");
        }
        JSONObject jsonObject = JSON.parseObject(String.valueOf(o));
        Object client_id = jsonObject.get("client_id");
        Object username = jsonObject.get("username");

        if (client_id == null || username == null) {
            throw new BusinessRuntimeException(-1, "code获取信息异常，请重新授权");
        }
        if (!Objects.equals(tokenRequest.getClient_id(), client_id)) {
            throw new BusinessRuntimeException(-1, "client_id校验异常，请重新授权");
        }
        redisTemplate.delete(CLIENT_AUTHORIZE_CODE + tokenRequest.getCode());
        return userService.generateToken(String.valueOf(username), oauthClientDetails.getAccessTokenValidity(), oauthClientDetails.getRefreshTokenValidity());
    }

    @Override
    public User getByToken(String access_token) {
        Object o = redisTemplate.opsForValue().get(UserServiceImpl.USER_LOGIN_TOKEN + access_token);
        if (null == o) {
            throw new BusinessRuntimeException(Errors.ACCESS_TOKEN_ERROR);
        }
        return userService.getByName(String.valueOf(o));
    }

    @Override
    public TokenResponse refreshToken(String refresh_token) {
        Object o = redisTemplate.opsForValue().get(UserServiceImpl.USER_LOGIN_REFRESH_TOKEN + refresh_token);
        if (null == o) {
            throw new BusinessRuntimeException(Errors.REFRESH_TOKEN_ERROR);
        }
        return userService.generateToken(String.valueOf(o), null, null);
    }

    @Override
    public Integer invalidAccessToken(String access_token) {
        if (redisTemplate.opsForValue().get(UserServiceImpl.USER_LOGIN_TOKEN + access_token) != null) {
            redisTemplate.delete(UserServiceImpl.USER_LOGIN_TOKEN + access_token);
        }
        return 1;
    }

    @Override
    public Integer invalidRefreshToken(String refresh_token) {
        if (redisTemplate.opsForValue().get(UserServiceImpl.USER_LOGIN_REFRESH_TOKEN + refresh_token) != null) {
            redisTemplate.delete(UserServiceImpl.USER_LOGIN_REFRESH_TOKEN + refresh_token);
        }
        return 1;
    }
}
